package com.project.thisDatabase.redis;

import com.project.annotation.function.RedisCommonExecutor;
import com.project.annotation.model.RedisBaseSetting;
import com.project.thisCommon.common.ConvertEntity;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName: RedisExecutor
 * @Auther: huabin
 * @Date: 2018/10/18 17:12
 * @Description:
 */
@ConditionalOnProperty(name = "spring.data.redis.enable", havingValue = "true")
@Component
public class RedisExecutor extends RedisBaseSetting {

    private RedisTemplate<Object,Object> redisTemplate;

    protected String readKey(String key) {
        if (StringUtils.isNotBlank(getRedis())) {
            return String.format("%s:%s%s%s",
                    this.getName(),
                    this.getPrefix(),
                    StringUtils.isBlank(key) ? this.getKey() : key,
                    this.getSuffix());
        }

        return key;
    }

    public void setRedisTemplate(RedisTemplate<Object,Object> template) {
        redisTemplate = template;
    }

    public synchronized Boolean addStringNx(String key,String value, Long time){
        return redisTemplate.opsForValue().setIfAbsent(readKey(key), value,  time, TimeUnit.MILLISECONDS);
    }

    public Boolean exists(String key) {
        return redisTemplate.hasKey(readKey(key));
    }

    /**
     * 插入String记录
     * @param key
     * @param value
     */
    public void addString(String key,String value){
        redisTemplate.opsForValue().set(readKey(key),value);
        setExpireMilliseconds(key, getTimeout());
    }

    public void addString(String key,String value, Long ms){
        addString(key,value);
        setExpireMilliseconds(key, ms);
    }

    public void addObject(String key,String name, Object value){
        String json = ConvertEntity.javaToJson(value);
        redisTemplate.opsForHash().put(readKey(key),name,json);
    }

    public void addObject(String key,String name, Object value, Long ms){
        addObject(key, name, value);
        setExpireMilliseconds(key, ms);
    }

    public void addObject(String key, Object value) {
        String json = ConvertEntity.javaToJson(value);
        addString(key, json);
    }

    public void addObject(String key, Object value, Long ms) {
        addObject(key, value);
        setExpireMilliseconds(key, ms);
    }

    public void addString(String key,String name, String value){
        redisTemplate.opsForHash().put(readKey(key),name,value);
    }

    public void addString(String key,String name, String value, Long ms){
        addString(key, name, value);
        setExpireMilliseconds(key, ms);
    }


    /**
     * 根据key删除记录
     * @param key
     */
    public void deleteByKey(String key){
        String key_val = readKey(key);
        if(redisTemplate.opsForValue().get(key_val) != null){
            redisTemplate.delete(key_val);
        }
    }

    /**
     * 根据key查找记录
     * @param key
     * @return
     */
    public String getByKey(String key){
        String result = null;
        String key_val = readKey(key);
        if(redisTemplate.opsForValue().get(key_val) != null){
            result = redisTemplate.opsForValue().get(key_val).toString();
        }
        return result;
    }

    public <T> T getObjectByKey(String key, Class cls){
        T result = null;
        Object jsonObj = redisTemplate.opsForValue().get(readKey(key));
        if(jsonObj != null) {
            String json = jsonObj.toString();
            result = ConvertEntity.jsonToJava(json, cls);
        }

        return result;
    }

    /**
     * 插入map记录(key-value)
     * @param key
     * @param name
     * @param obj
     */
    public void addMap(String key, String name, Object obj){
        String val = null;
        String key_val = readKey(key);
        if(obj instanceof String){
            val = obj.toString();
        } else {
            val = ConvertEntity.javaToJson(obj);
        }
        redisTemplate.opsForHash().put(key_val,name,val);
    }

    public void addMap(String key, String name, Object obj, Long ms){
        addMap(key, name, obj);
        setExpireMilliseconds(key, ms);
    }

    public void addMap(String key, Map map){
        map.forEach((k,v)->{
            addMap(key, k.toString(), v);
        });
    }

    public void addHashMap(String key, String name, String value){
        redisTemplate.opsForHash().put(readKey(key), name, value);
    }

    public void addHashMap(String key, String name, String value, Long ms){
        addHashMap(key, name, value);
        setExpireMilliseconds(key, ms);
    }

    public String getHashMap(String key, String name){
        return redisTemplate.opsForHash().get(readKey(key), name).toString();
    }

    public <T> T getHashMapObject(String key, String name, Class cls){
        T result = null;
        Object jsonObj = redisTemplate.opsForHash().get(readKey(key), name);
        if(jsonObj != null) {
            String json = jsonObj.toString();
            result = ConvertEntity.jsonToJava(json, cls);
        }

        return result;
    }

//    /**
//     * 插入map记录(map)
//     * @param key
//     * @param map
//     */
//    public void addMap (String key, Map<String,String> map){
//        for (Map.Entry<String, String> entry : map.entrySet()) {
//            redisTemplate.opsForHash().put(key,entry.getKey(), entry.getValue());
//        }
//    }

    /**
     * 根据key和属性name删除map记录
     * @param key
     * @param name
     */
    public void deleteMap(String key,String name){
        if (hasMapKey(key, name)) {
            String key_val = readKey(key);
            if(redisTemplate.opsForHash().get(key_val,name) != null){
                redisTemplate.opsForHash().delete(key_val,name);
            }
        }
    }

    public Boolean hasMapKey(String key,String name){
        return redisTemplate.opsForHash().hasKey(readKey(key), name);
    }

    /**
     * 根据key查找map记录
     * @param key
     * @param name
     * @return
     */
    public String getMap(String key,String name){
        String result = null;
        String key_val = readKey(key);
        if(redisTemplate.opsForHash().get(key_val,name) != null){
            result = redisTemplate.opsForHash().get(key_val,name).toString();
        }
        return result;
    }

    public synchronized boolean addSet(String key, String value){
        String key_val = readKey(key);
        if (!redisTemplate.opsForSet().isMember(key_val, value)){
            redisTemplate.opsForSet().add(key_val, value);
            return true;
        }
        return false;
    }

    public boolean hasSetKey(String key, String value){
        return redisTemplate.opsForSet().isMember(readKey(key), value);
    }

    /**
     * 添加List记录
     * @param key
     * @param value
     */
    public void addList(String key,String value){
        redisTemplate.opsForList().leftPush(readKey(key),value);
    }

    public void addList(String key,String value, Long ms){
        addList(key,value);
        setExpireMilliseconds(key, ms);
    }

    public void addListByObject(String key, Object value){
        String key_val = readKey(key);
        if(value instanceof List){
            ((List)value).forEach((v)->{
                String json = ConvertEntity.javaToJson(value);
                redisTemplate.opsForList().leftPush(key_val, json);
            });
        } else {
            String json = ConvertEntity.javaToJson(value);
            redisTemplate.opsForList().leftPush(key_val, json);
        }

    }

    public void addListByObject(String key, Object value, Long ms){
        addListByObject(key, value);
        setExpireMilliseconds(key, ms);
    }

    /**
     * 查找List记录
     * @param key
     */
    public List<Object> getList(String key){
        List list = null;
        String key_val = readKey(key);
        if(redisTemplate.opsForList().range(key_val,0,-1) != null){
            list= redisTemplate.opsForList().range(key_val,0,-1);
        }
        return list;
    }

    public <T> List<T> getList(String key, Class cls){
        List list = new ArrayList<T>();
        String key_val = readKey(key);
        if(redisTemplate.opsForList().range(key_val,0,-1) != null){
            List jsonList = redisTemplate.opsForList().range(key_val,0,-1);
            jsonList.forEach((v)->{
                list.add(ConvertEntity.jsonToJava(v.toString(),cls));
            });
        }
        return list;
    }

    public void deleteList(String key){
        String key_val = readKey(key);
        List list = redisTemplate.opsForList().range(key_val,0,-1);
        list.forEach(f->{
            redisTemplate.opsForList().remove(key_val, -1, f);
        });
    }


    /**
     * 设置过期时间-单位（天）
     * @param key
     * @param temp
     */
    public void setExpireDays(String key,int temp){
        if (temp >= 0) {
            redisTemplate.expire(readKey(key),temp, TimeUnit.DAYS);
        }
    }

    /**
     * 设置过期时间-单位（分）
     * @param key
     * @param temp
     */
    public void setExpireMinutes(String key,int temp){
        if (temp >= 0) {
            redisTemplate.expire(readKey(key),temp, TimeUnit.MINUTES);
        }
    }

    /**
     * 设置过期时间-单位（秒）
     * @param key
     * @param temp
     */
    public void setExpireSeconds(String key,int temp){
        if (temp >= 0) {
            redisTemplate.expire(readKey(key),temp, TimeUnit.SECONDS);
        }
    }

    public void setExpireMilliseconds(String key, long temp){
        if (temp >= 0) {
            redisTemplate.expire(readKey(key),temp, TimeUnit.MILLISECONDS);
        }
    }
}
